/* EIX Message and protocol library
 * Copyright (C) 2010 Jorge Luis Zapata
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.
 * If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef EIX_H_
#define EIX_H_

/**
 * @mainpage Eix
 * @section intro Introduction
 * @section features Features
 * @section dependencies Dependencies
 * - Eina
 * - Ender
 * @file
 * @brief Eix API
 */

#include "Eina.h"
#include "Ender.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * @}
 * @defgroup Eix_Main_Group Main
 * @{
 */

EAPI void eix_init(void);
EAPI void eix_shutdown(void);


/**
 * @}
 * @defgroup Eix_Errors_Group Errors
 * @{
 */

typedef enum _Eix_Error_Code
{
	EIX_ERR_NONE,
	EIX_ERR_NEXIST,  /* a reixest for some element that doesnt exist */
	EIX_ERR_CODEC,   /* bad encoding or decoding */
	EIX_ERR_TIMEOUT, /* timeout error */
	EIX_ERRORS,
} Eix_Error_Code;

typedef struct _Eix_Error
{
	Eix_Error_Code code;
	char *msg;
} Eix_Error;

EAPI void eix_error_set(Eix_Error *e,
		Eix_Error_Code code, const char *str);

static inline Eina_Bool eix_error_is_set(Eix_Error *e)
{
	if (e->code != EIX_ERR_NONE) return EINA_TRUE;
	else return EINA_FALSE;
}

/**
 * @}
 * @defgroup Eix_Message_Group Message
 * @{
 */

typedef struct _Eix_Message Eix_Message;

extern Eix_Message *EIX_MESSAGE_ERROR;

EAPI Eix_Message * eix_message_add(Ender_Descriptor *edd, Eix_Message *reply,
		double timeout);
EAPI Eix_Message * eix_message_reply_get(Eix_Message *thiz);


/**
 * @}
 * @defgroup Eix_Transport_Group Transport
 * @{
 */

typedef struct _Eix_Transport Eix_Transport;
typedef void (*Eix_Transport_Process_Request)(Eix_Transport *t,
		Eina_Bool to_read, Eina_Bool to_write, void *data);
typedef void (*Eix_Transport_Reply_Cb)(void *reply, Eix_Error *err, void *user_data);

typedef enum _Eix_Transport_State
{
	EIX_TRANSPORT_STATE_UNKNOWN,
	EIX_TRANSPORT_STATE_INIT,
	EIX_TRANSPORT_STATE_CONNECTING,
	EIX_TRANSPORT_STATE_CONNECTED,
	EIX_TRANSPORT_STATES
} Eix_Transport_State;

EAPI Eix_Transport * eix_transport_unix_tcp_new(const char *path);
EAPI const char * eix_transport_unix_tcp_path_get(Eix_Transport *thiz);
EAPI int eix_transport_unix_tcp_fd_get(Eix_Transport *thiz);

EAPI Eix_Transport_State eix_transport_state_get(Eix_Transport *thiz);
EAPI Eina_Bool eix_transport_serves(Eix_Transport *thiz);

EAPI void eix_transport_process_required(Eix_Transport *thiz, Eina_Bool *to_read,
		Eina_Bool *to_write);
EAPI void eix_transport_process_request_set(Eix_Transport *thiz,
		Eix_Transport_Process_Request req, void *data);

/**
 * @}
 * @defgroup Eix_Server_Group Server
 * @{
 */

typedef struct _Eix_Server Eix_Server;

typedef void (*Eix_Server_Socket_Data)(Eix_Server *s, void *socket,
		const Eix_Message *m, void *data, void *reply,
		Eix_Error *error, void *user_data);
typedef void (*Eix_Server_Socket_Add)(Eix_Server *s, void *socket,
		void *user_data);
typedef void (*Eix_Server_Socket_Del)(Eix_Server *s, void *socket,
		void *user_data);

typedef struct _Eix_Server_Descriptor
{
	Eix_Server_Socket_Add add;
	Eix_Server_Socket_Del del;
	Eix_Server_Socket_Data data;
} Eix_Server_Descriptor;

EAPI Eix_Server * eix_server_connect(Eix_Transport *t,
		Eix_Server_Descriptor *descriptor, void *data);
EAPI Eix_Server * eix_server_new(Eix_Transport *t,
		Eix_Server_Descriptor *descriptor, void *data);

EAPI void eix_server_sync(Eix_Server *e);
EAPI Eina_Bool eix_server_message_send(Eix_Server *es, Eix_Message *m,
		void *data, void *rdata, Eix_Error *err, uint32_t *id);
EAPI Eina_Bool eix_server_message_send_deferred(Eix_Server *thiz, Eix_Message *m,
		void *data, Eix_Transport_Reply_Cb cb, const void *user_data);

EAPI void eix_server_data_set(Eix_Server *s, const char *str, void *data);
EAPI void * eix_server_data_get(Eix_Server *s, const char *str);
EAPI void eix_server_del(Eix_Server *s);
EAPI const Eina_List * eix_server_client_get(Eix_Server *thiz);
EAPI Eix_Transport * eix_server_transport_get(Eix_Server *thiz);
EAPI void eix_server_process(Eix_Server *thiz, Eina_Bool can_read, Eina_Bool can_write);

/**
 * @}
 * @defgroup Eix_Client_Group Client
 * @{
 */

typedef struct _Eix_Client Eix_Client;

EAPI Eix_Transport * eix_client_transport_get(Eix_Client *thiz);
EAPI void eix_client_data_set(Eix_Client *thiz, const char *str, void *data);
EAPI void * eix_client_data_get(Eix_Client *thiz, const char *str);

EAPI void eix_client_del(Eix_Client *c);
EAPI Eix_Server * eix_client_server_get(Eix_Client *c);
EAPI Eina_Bool eix_client_message_send(Eix_Client *thiz, Eix_Message *m,
		void *data, void *rdata, Eix_Error *err, uint32_t *id);
EAPI Eina_Bool eix_client_message_send_deferred(Eix_Client *thiz,
		Eix_Message *m, void *data, Eix_Transport_Reply_Cb cb,
		const void *user_data);
EAPI void eix_client_process(Eix_Client *thiz, Eina_Bool can_read, Eina_Bool can_write);

/**
 * @}
 */

#ifdef __cplusplus
}
#endif

#endif /*_EIX_H*/
